%{
  #include <iostream>
  #include <cerrno>
  #include <climits>
  #include <cstdlib>
  #include <string>

  #include "parser.hpp"  //包含由parser.y生成的头文件
  #include "scanner.h"   //包含yyFlexLexer子类的头文件
  #include "location.hh" //包含位置调试信息头文件

  static Marker::location loc;//声明位置实例
  #define YY_USER_ACTION  loc.columns (yyleng); /* 定义了YY_USER_ACTION，该宏在每个记号的语义动作之前被调用，来根据记号的长度设置位置的信息 */

  #undef yywrap
  #define yywrap() 1

  using namespace Marker;
  #define yyterminate() Parser::make_END(loc);
%}
/* 声明使用C++版本FLEXER，c++是大小写不敏感的 */
%option c++

/* 支持调试 */
%option noyywrap debug

/* 使用Scanner::yylex() */
%option yyclass="Scanner"

/* 一些与编译常量使用该前缀否则为yy */
%option prefix="Marker_"

/* user */
%x COMMENT

digit         ([0-9])
alpha         ([A-Za-z_])

integer       ({digit}+)
identifier    ({alpha}({alpha}|{digit})*)
op_assign     (([+*/%&|^-]|<<|>>)=)

%%
%{
  // C++ 兼容的词法分析器的规则，step函数把位置的起始值设置为与结束值相等，这样位置就指向了上一个极少的结束位置。
  loc.step();
%}


{identifier} {
    return Parser::make_IDENTIFIER(yytext, loc);
}

{integer} {
	return Parser::make_INTEGER(atoi(yytext), loc);
}

"//" {
	BEGIN COMMENT;
}

"++" {
	return Parser::make_OP_INC(yytext, loc);
}

"--" {
	return Parser::make_OP_DEC(yytext, loc);
}

">>" {
	return Parser::make_OP_LSR(yytext, loc);
}

"<<" {
	return Parser::make_OP_LSL(yytext, loc);
}

"<" {
	return Parser::make_OP_LT(yytext, loc);
}

"<=" {
	return Parser::make_OP_LE(yytext, loc);
}

">" {
	return Parser::make_OP_GT(yytext, loc);
}

">=" {
	return Parser::make_OP_GE(yytext, loc);
}

"==" {
	return Parser::make_OP_EQ(yytext, loc);
}

"!=" {
	return Parser::make_OP_NE(yytext, loc);
}

"&&" {
	return Parser::make_OP_AND(yytext, loc);
}

"||" {
	return Parser::make_OP_OR(yytext, loc);
}

{op_assign} {
	return Parser::make_OP_ASSIGN(yytext, loc);
}

"+" {
    return Parser::make_CHAR_ADD(yytext[0], loc);
}

"-" {
    return Parser::make_CHAR_MINUS(yytext[0], loc);
}

"=" {
    return Parser::make_CHAR_EQUAL(yytext[0], loc);
}

"(" {
    return Parser::make_CHAR_LPARENTHESES(yytext[0], loc);
}

")" {
    return Parser::make_CHAR_RPARENTHESES(yytext[0], loc);
}

"!" {
    return Parser::make_CHAR_EXCLAMATION_POINT(yytext[0], loc);
}

"~" {
    return Parser::make_CHAR_TILDE(yytext[0], loc);
}

"*" {
    return Parser::make_CHAR_TIMES(yytext[0], loc);
}

"/" {
    return Parser::make_CHAR_SLASH(yytext[0], loc);
}

"%" {
    return Parser::make_CHAR_MOD(yytext[0], loc);
}

"&" {
    return Parser::make_CHAR_AND(yytext[0], loc);
}

"^" {
    return Parser::make_CHAR_XOR(yytext[0], loc);
}

"|" {
    return Parser::make_CHAR_OR(yytext[0], loc);
}

"?" {
    return Parser::make_CHAR_QUESTION_MARK(yytext[0], loc);
}

":" {
    return Parser::make_CHAR_COLON(yytext[0], loc);
}

"\n" {}
. {}

<COMMENT>\n {
	BEGIN INITIAL;
}

<COMMENT>. {}

<<EOF>> { return Parser::make_END(loc); }

%%
